using Aurora.Redis.Tools;
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using ServiceStack.Redis;

namespace Aurora.Redis.ServiceStackRedis;

public class ServiceStackRedisCache : IRedisCache, IDistributedCache
{
    private readonly IRedisClient _redisClient;

    public ServiceStackRedisCache()
    {
        _redisClient = ServiceStackRedisFactory.Get();
    }

    ~ServiceStackRedisCache()
    {
        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "进行了析构函数");
        if (_redisClient != null)
        {
            _redisClient.Dispose();
        }
    }

    void IDisposable.Dispose()
    {
        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "进行了Dispose");
        if (_redisClient != null)
        {
            _redisClient.Dispose();
        }
    }

    public bool Add(string key, string value, TimeSpan timeSpan)
    {
        return _redisClient.Set(key, value, timeSpan);
    }

    public bool Add<T>(string key, T value, TimeSpan timeSpan)
    {
        return _redisClient.Set(key, value, timeSpan);
    }

    public T LPop<T>(string key)
    {
        var data = _redisClient.RemoveStartFromList(key); //RemoveStartFromListAsync
        if (!string.IsNullOrEmpty(data))
        {
            return JsonConvert.DeserializeObject<T>(data);
        }

        return default;
    }

    public T Get<T>(string key)
    {
        return _redisClient.Get<T>(key);
    }

    public long Del(string key)
    {
        return Exec(redis =>
        {
            redis.Delete(key);
            return 1;
        });
    }

    private T Exec<T>(Func<IRedisClient, T> func)
    {
        return func(_redisClient);
    }

    public async Task<long> DelByPatternAsync(string pattern)
    {
        if (string.IsNullOrEmpty(pattern))
            return 0;
        pattern = CacheTool.PatternRegexReplace(pattern);
        var keys = Exec(redis =>
        {
            var values = redis.SearchKeys(pattern);
            return values?.ToList();
        });
        if (keys != null && keys.Any())
        {
            return Exec(redis =>
            {
                redis.RemoveAll(keys.ToArray());
                return keys.Count;
            });
        }

        return default;
    }

    public async Task<List<string>> GetKeys(string pattern)
    {
        if (string.IsNullOrEmpty(pattern))
            return new List<string>();
        pattern = CacheTool.PatternRegexReplace(pattern);
        var keys = Exec(redis =>
        {
            var values = redis.SearchKeys(pattern);
            return values?.ToList();
        });
        return keys;
    }

    public Task<bool> AddAsync(string key, string value, TimeSpan timeSpan)
    {
        throw new NotImplementedException();
    }

    public Task<bool> AddAsync<T>(string key, T value, TimeSpan timeSpan)
    {
        throw new NotImplementedException();
    }

    public Task<T> LPopAsync<T>(string key)
    {
        throw new NotImplementedException();
    }

    public Task<T> GetAsync<T>(string key)
    {
        throw new NotImplementedException();
    }

    public Task<long> DelAsync(string key)
    {
        throw new NotImplementedException();
    }

    public Task IncrementAsync(string key)
    {
        throw new NotImplementedException();
    }

    public Task IncrementAsync(string key, int value = 1, TimeSpan? ttl = null)
    {
        throw new NotImplementedException();
    }

    public byte[] Get(string key)
    {
        throw new NotImplementedException();
    }

    public Task<byte[]> GetAsync(string key, CancellationToken token = default)
    {
        throw new NotImplementedException();
    }

    public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
    {
        throw new NotImplementedException();
    }

    public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default)
    {
        throw new NotImplementedException();
    }

    public void Refresh(string key)
    {
        throw new NotImplementedException();
    }

    public Task RefreshAsync(string key, CancellationToken token = default)
    {
        throw new NotImplementedException();
    }

    public void Remove(string key)
    {
        throw new NotImplementedException();
    }

    public Task RemoveAsync(string key, CancellationToken token = default)
    {
        throw new NotImplementedException();
    }
}